package com.neusoft.neuiotms.dcom.fixture;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.activiti.editor.language.json.converter.util.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.neusoft.bizcore.cache.caching.CacheService;
import com.neusoft.neuiotms.common.converter.DictionaryConverter;
import com.neusoft.neuiotms.common.dto.DictionaryDTO;
import com.neusoft.neuiotms.common.model.Dictionary;
import com.neusoft.neuiotms.common.model.DictionaryType;
import com.neusoft.neuiotms.common.repository.DictionaryRepository;
import com.neusoft.neuiotms.common.repository.DictionaryTypeRepository;
import com.neusoft.neuiotms.dcom.constants.DCOMConstants;
import com.neusoft.neuiotms.dcom.model.Project;
import com.neusoft.neuiotms.dcom.repository.ProjectRepository;
import com.univocity.parsers.annotations.NullString;
import com.univocity.parsers.annotations.Parsed;
import com.univocity.parsers.common.processor.BeanListProcessor;
import com.univocity.parsers.csv.CsvParser;
import com.univocity.parsers.csv.CsvParserSettings;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
@Order(value = 2)
public class DcomFixture implements CommandLineRunner {

    @Autowired
    private DictionaryTypeRepository dictionaryTypeRepository;
    @Autowired
    private DictionaryRepository dictionaryRepository;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private DictionaryConverter dictionaryConverter;

    public static String CACHE_COMMON_DIC = "CACHE_COMMON_DIC";
    @Autowired
    private ProjectRepository projectRepository;

    @Override
    public void run(final String... args) throws Exception {
        DcomFixture.log.info("DCOM 初始化 开始");
        this.initDictionaryType();
        this.initDicCache();
        this.initProject();
        DcomFixture.log.info("DCOM 初始化 结束");

    }

    // 初始化项目
    private void initProject() {
        final List<Project> list = this.projectRepository.findAll();
        if (CollectionUtils.isEmpty(list)) {
            final Project model = new Project();
            model.setName("海南省政务信息化公共服务能力支撑项目（D包）-海南省省直单位信息化基础设施移交及运维服务");
            model.setCode("HN");
            model.setStartTime(new Date());
            model.setEndTime(new Date());
            this.projectRepository.save(model);
        }

    }

    private void initDicCache() {
        final List<DictionaryType> types = this.dictionaryTypeRepository.findAll();
        final List<Dictionary> list = this.dictionaryRepository.findAll();

        final List<DictionaryDTO> cacheList = new ArrayList<>();
        types.forEach(m -> {
            cacheList.clear();
            list.stream().filter(s -> s.getDictionaryType().getType().equals(m.getType()))
                    .map(k -> this.dictionaryConverter.toDTO(k)).forEach(cacheList::add);
            if (!this.cacheService.isInCache(DcomFixture.CACHE_COMMON_DIC, m.getType())) {
                this.cacheService.put(DcomFixture.CACHE_COMMON_DIC, m.getType(), cacheList);
            }
        });

    }

    private void initDictionaryType() throws IOException {
        DcomFixture.log.info("DCOM初始化字典表数据开始");
        final DictionaryType type = this.dictionaryTypeRepository.findByType(DCOMConstants.INSPECTION_VALUE_TYPE);
        if (type != null) {
            DcomFixture.log.info("无需初始化字典表");
            return;
        }

        final CsvParserSettings settings = new CsvParserSettings();
        settings.getFormat().setLineSeparator("\n");
        // 可以将解析器配置成自动检测输入中的行分隔符
        settings.setLineSeparatorDetectionEnabled(true);
        settings.setHeaderExtractionEnabled(true);

        final BeanListProcessor<DictionaryTypeBean> processor = new BeanListProcessor<>(DictionaryTypeBean.class);
        settings.setProcessor(processor);

        final CsvParser parser = new CsvParser(settings);
        final org.springframework.core.io.Resource csvFile = this.applicationContext
                .getResource("classpath:fixture/dcom_neuiot_dictionary_type.csv");

        if (!csvFile.exists()) {
            return;
        }
        parser.parse(csvFile.getInputStream());
        final List<DictionaryTypeBean> typeBeans = processor.getBeans();
        final List<DictionaryBean> dictionarys = this.initDictionary();

        final List<Dictionary> saveList = new ArrayList<>();
        for (final DictionaryTypeBean typeBean : typeBeans) {
            final DictionaryType setting = new DictionaryType();
            BeanUtils.copyProperties(typeBean, setting);
            final DictionaryType model = this.dictionaryTypeRepository.save(setting);
            final List<DictionaryBean> everyTypedictionary = dictionarys.stream()
                    .filter(t -> t.getDictionary_type_id() == typeBean.getId()).collect(Collectors.toList());
            final List<Dictionary> dictionary = everyTypedictionary.stream().map(k -> {
                final Dictionary d = new Dictionary();
                BeanUtils.copyProperties(k, d);
                d.setDictionaryType(model);
                return d;
            }).collect(Collectors.toList());
            saveList.addAll(dictionary);
        }

        if (!saveList.isEmpty()) {
            this.dictionaryRepository.saveAll(saveList);
        }
        DcomFixture.log.info("初始化字典表数据结束");
    }

    private List<DictionaryBean> initDictionary() throws IOException {
        final CsvParserSettings dictionarySettings = new CsvParserSettings();
        dictionarySettings.getFormat().setLineSeparator("\n");
        // 可以将解析器配置成自动检测输入中的行分隔符
        dictionarySettings.setLineSeparatorDetectionEnabled(true);
        dictionarySettings.setHeaderExtractionEnabled(true);

        final BeanListProcessor<DictionaryBean> dictionaryprocessor = new BeanListProcessor<>(DictionaryBean.class);
        dictionarySettings.setProcessor(dictionaryprocessor);

        final CsvParser parser1 = new CsvParser(dictionarySettings);
        final org.springframework.core.io.Resource csvDictionaryFile = this.applicationContext
                .getResource("classpath:fixture/dcom_neuiot_dictionary.csv");

        if (!csvDictionaryFile.exists()) {
            return new ArrayList<>();
        }

        parser1.parse(csvDictionaryFile.getInputStream());
        return dictionaryprocessor.getBeans();
    }

    @Getter
    @Setter
    @ToString
    public static class DictionaryTypeBean {
        @Parsed(field = "id")
        private Long id;

        @Parsed(field = "text")
        private String text;

        @Parsed(field = "type")
        private String type;

    }

    @Getter
    @Setter
    @ToString
    public static class DictionaryBean {
        @Parsed(field = "id")
        private Long id;

        @Parsed(field = "code")
        private String code;

        @NullString(nulls = {"null" })
        @Parsed(field = "sort")
        private Integer sort;

        @Parsed(field = "text")
        private String text;

        @Parsed(field = "dictionary_type_id")
        private Long dictionary_type_id;

    }
}
